<script setup lang="ts">
import {computed, Fragment, useSlots, type VNode} from 'vue'
import type CardProp from "@/components/card/type/CardProp.ts";

const $prop = withDefaults(defineProps<CardProp>(), {
  bgColor: '#FFF',
  width: '100%',
  height: '100px',
  tagColor: 'transparent',
  beatOnHover: false
})

const slots = useSlots()

// 递归检查VNode是否有有效内容
const hasValidVNodeContent = (vnode: VNode): boolean => {
  // 如果是注释节点 (Vue内部使用Symbol来标识注释节点)
  if (vnode.type === Comment || vnode.type.toString().includes('v-cmt')) {
    return false
  }

  // 如果是文本节点
  if (typeof vnode.children === 'string') {
    return vnode.children.trim() !== ''
  }

  // 如果是数组（多个子节点）
  if (Array.isArray(vnode.children)) {
    return vnode.children.some(child =>
        typeof child === 'object' && child !== null && hasValidVNodeContent(child as VNode)
    )
  }

  // 如果是Fragment
  if (vnode.type === Fragment) {
    if (Array.isArray(vnode.children)) {
      return vnode.children.some(child =>
          typeof child === 'object' && child !== null && hasValidVNodeContent(child as VNode)
      )
    }
    return false
  }

  // 如果是组件或元素节点，认为是有效内容
  return typeof vnode.type === 'string' || typeof vnode.type === 'object';
}

// 判断卡片是否是有效内容
const hasValidContent = computed(() => {
  // 检查是否有默认插槽函数
  if (!slots.default) {
    return false
  }

  const defaultSlot = slots.default()

  // 如果插槽内容为空或长度为0，说明没有有效内容
  if (!defaultSlot || defaultSlot.length === 0) {
    return false
  }

  // 检查每个VNode是否有有效内容
  return defaultSlot.some(vnode => {

    // 跳过注释节点 (Vue内部使用Symbol来标识注释节点)
    if (vnode.type === Comment || vnode.type.toString().includes('v-cmt')) {
      return false
    }

    // 检查是否有有效内容
    return hasValidVNodeContent(vnode)
  })
})
</script>

<template>
  <div class="card-container" :class="{'card-container-beat': beatOnHover}">
    <template v-if="hasValidContent">
      <slot/>
    </template>
    <template v-else>
      <div class="card-default">
        加载中...
      </div>
    </template>
  </div>
</template>

<style scoped>
.card-container {
  position: relative;
  background-color: v-bind(bgColor);
  min-width: v-bind(width);
  min-height: v-bind(height);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  border-radius: 3px;
  padding: 10px;

  display: flex;
  justify-content: center;
}

.card-container-beat:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

.card-default {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;
  font-size: 16px;
  color: #666;
  user-select: none;
}
</style>